/*
 * CPLEXUtility.c
 *
 *  Created on: 04/giu/2013
 *      Author: Ialenti Andrea, Marangon Fabio
 */

#include "../headers/CPLEXProblemGenerator.h"
#include "../headers/CPLEXUtility.h"
#include "../headers/Printer.h"
#include "../headers/StatusCodes.h"
#include "../headers/Utility.h"

#include <string.h>

Status getCPLEXSol(const Config *cfg, CPXENVptr env, CPXLPptr lp, double **x, int *size) {
	char *funcName = initCharArray(cfg->NAME_LEN);
	sprintf(funcName, "getCPLEXSol");

	//	Get the number of variables (columns) in the current problem.
	*size = CPXgetnumcols(env, lp);
	if (*size == CPX_SUCCESS) {
		fprintf(stdout, "***'%s': error retrieving problem's number of columns!\n", funcName);
		freeCharArray(funcName);
		return ERR_CPX;
	}

	//	Allocate memory for the array of 'x' variables and retrieve them.
	*x = initDblArray(*size);
	if (*x == NULL) {
		fprintf(stdout, "***'%s': memory allocation error on array 'x'!\n", funcName);
		freeCharArray(funcName);
		return ERR_MEM_ALLOC;
	}

	//	Get CPLEX solution.
	int cpxStat = CPXgetx(env, lp, *x, 0, *size - 1);
	if (cpxStat != CPX_SUCCESS) {
		fprintf(stdout, "***'%s': error retrieving the solution 'x'. CPLEX status: %d.\n", funcName, cpxStat);
		freeCharArray(funcName);
		return ERR_CPX;
	}

	//	Free memory.
	freeCharArray(funcName);
	return SUCCESS;
}

Status plotSolution(const Config *cfg, CPXENVptr env, CPXLPptr lp, const Problem *p, const Graph *g, int solCnt, bool ps, bool opt) {
	char *funcName = initCharArray(cfg->NAME_LEN);
	sprintf(funcName, "plotSolution");

	int i, nEdges, cpxStat, idx1, idx2;
	double solution = 0, *x;

	//	Get the list of edges chosen in the current solution.
	Status status = getCPLEXSol(cfg, env, lp, &x, &nEdges);
	if(status != SUCCESS) {
		fprintf(stdout, "***'%s': error retrieving the solution 'x'. . .\n", funcName);
		freeCharArray(funcName);
		return ERR_GENERIC;
	}

	//	Get the solution cost.
	for (i = 0; i < nEdges; i++)
		if (x[i] > 1 - cfg->EPS) {
			getEdgeNodes(p, i, &idx1, &idx2);
			solution += g->costs_origin[idx1][idx2];
		}

	//	Plot the solution.
	char *name = initCharArray(cfg->NAME_LEN);
	char *title = initCharArray(cfg->NAME_LEN);
	char *color = initCharArray(cfg->NAME_LEN);
	strcpy(color, cfg->COLOR_BLUE);
	if (solCnt == 0) {
		sprintf(name, "%soptSolution.dat", cfg->PLT_PATH);
		if (opt) {
			sprintf(title, "TSP optimal solution for '%s'. Solution cost = %0.0f", p->name, solution);
			strcpy(color, cfg->COLOR_GREEN);
		}
		else
			sprintf(title, "Best known solution for '%s'. Solution cost = %0.0f", p->name, solution);
	} else if (solCnt == -1) {
		sprintf(name, "%sfirstSol.dat", cfg->PLT_PATH);
		sprintf(title, "First CPLEX solution (no SECs) for '%s'. Solution cost = %0.0f", p->name, solution);
	} else if (solCnt == -2) {
		sprintf(name, "%sfirstSol_cb.dat", cfg->PLT_PATH);
		if (opt) {
			sprintf(title, "TSP optimal solution (found using callbacks) for '%s'. Solution cost = %0.0f", p->name, solution);
			strcpy(color, cfg->COLOR_GREEN);
		}
		else
			sprintf(title, "Best known solution (found using callbacks) for '%s'. Solution cost = %0.0f", p->name, solution);
	} else {
		if (ps){
			sprintf(name, "%sPS_solution#%d.dat", cfg->PLT_PATH, solCnt);
			sprintf(title, "CPLEX proximity search solution #%d for '%s'. Solution cost = %0.0f", solCnt, p->name, solution);
		}
		else {
			sprintf(name, "%ssolution#%d.dat", cfg->PLT_PATH, solCnt);
			sprintf(title, "CPLEX solution #%d for '%s'. Solution cost = %0.0f", solCnt, p->name, solution);
		}
	}
	cpxStat = plotCPLEXSol(cfg, x, p, g, name, title, color);

	//	Free memory.
	freeCharArray(funcName);
	freeCharArray(name);
	freeCharArray(title);
	freeCharArray(color);
	freeDblArray(x);
	return cpxStat;
}
